#include <iostream>
using namespace std;

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>

int main()
{
    int pipeFd[2];      //0为读端，1为写端

    /* 创建管道 */
    pipe(pipeFd);

    /* 查看管道大小 */
    cout << "pipe size" << fpathconf(pipeFd[0], _PC_PIPE_BUF) << endl;
    cout << "pipe size" << fpathconf(pipeFd[1], _PC_PIPE_BUF) << endl;
    

    /* 创建进程 */
    pid_t pid = fork();
    if(pid < 0)
    {
        perror("fork error:");
        _exit(-1);
    }
    else if(pid == 0)
    {   /* 子进程 */
        close (pipeFd[1]);
        sleep(3);

        /* 设置文件描述符为非阻塞(没有数据就走) 直接改成非阻塞就读不到内容了*/
        /* 1、得到文件描述符的原本属性 */
        int flags = fcntl(pipeFd[0], F_SETFL);
        /* 2、在原本的属性上面增加新的属性（非阻塞） */
        flags |= O_NONBLOCK;
        /* 3、设置附加上的属性到文件描述符 */
        fcntl(pipeFd[0], F_SETFL, flags);

        int recvMoney = 0;
        /* 从管道读取数据 */
        //read(pipeFd[0], &recvMoney, sizeof(recvMoney));

        char buffer[3];             //不能用char *，因为实际上创建了一个指向 char 类型指针的数组，而不是一个字符数组，所以会打印指针地址
        //每次读两个但是写3，是为了保留一个\n的位置
        int readBytes = 0;
        while(1)
        {
            readBytes = read(pipeFd[0], buffer, sizeof(buffer) - 1);
            if(readBytes < 0)
            {
                if(errno == EAGAIN)
                {
                    cout << "non block..." << endl;
                    _exit(-1);
                }
                else
                {
                    perror("read pipe error:");
                    /* 退出进程 */
                    _exit(-1);
                }
                
            }
            if(readBytes < sizeof(buffer) - 1)
            {
                cout << "buffer:" << buffer << endl;
                break;
            }
            cout << "buffer:" << buffer << endl;
            memset(buffer, 0, sizeof(buffer));
    
        }
        

        //cout << "recvMoney:" << recvMoney << endl;
    }  
    else
    {   /* 父进程 只写，关闭读端*/
        close (pipeFd[0]);
        int money = 50000;

        sleep(3);      //父进程延时向管道写数据

        /* 向管道写hello world */
        const char * buf ="helloworld";
        write(pipeFd[1], static_cast<const void *>(buf), strlen(buf));


        // /* 向管道写端写数据 */
        // write(pipeFd[1], static_cast<const void *>(&money), sizeof(money));

        /* 回收子进程资源 */
        wait(NULL);
    }

    return 0;
}